package com.lcy.web.base

import java.lang.reflect.Type
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import javax.ws.rs.Consumes
import javax.ws.rs.Produces
import javax.ws.rs.ext.ParamConverter
import javax.ws.rs.ext.ParamConverterProvider
import javax.ws.rs.ext.Provider

/**
 * 参数转换，将 url 中传入的 QueryParam 转换为相应类型的参数
 * Created by loucunyin on 7/5/17.
 */
@Provider
@Produces("*/*")
@Consumes("*/*")
open class MyConverterProvider : ParamConverterProvider {
    override fun <T : Any?> getConverter(rawType: Class<T>, genericType: Type?, annotations: Array<out Annotation>?): ParamConverter<T>? {
        val default = object : ParamConverter<T> {
            override fun fromString(value: String?): T? {
                if (value.isNullOrBlank()) {
                    return null
                }
                return rawType.cast(value)
            }

            override fun toString(value: T): String {
                return value.toString()
            }
        }
        when (rawType.name) {
        // kotlin 获取到的数据类型对应 java 基本数据类型
            "java.lang.Integer" -> return object : ParamConverter<T> {
                override fun fromString(value: String?): T? {
                    if (value.isNullOrBlank()) {
                        return null
                    }
                    val number: Int? = value?.toIntOrNull() ?: return null
                    return rawType.cast(number)
                }

                override fun toString(value: T?): String? {
                    if (value == null) {
                        return null
                    }
                    return value.toString()
                }
            }
            "java.lang.Long" -> return object : ParamConverter<T> {
                override fun fromString(value: String?): T? {
                    if (value.isNullOrBlank() ) {
                        return null
                    }
                    val number: Long? = value?.toLongOrNull() ?: return null
                    return rawType.cast(number)
                }

                override fun toString(value: T?): String? {
                    if (value == null) {
                        return null
                    }
                    return value.toString()
                }
            }
            "java.lang.Float" -> return object : ParamConverter<T> {
                override fun fromString(value: String?): T? {
                    if (value.isNullOrBlank() ) {
                        return null
                    }
                    val number: Float? = value?.toFloatOrNull() ?: return null
                    return rawType.cast(number)
                }

                override fun toString(value: T?): String? {
                    if (value == null) {
                        return null
                    }
                    return value.toString()
                }
            }
            Date::class.java.name -> return object : ParamConverter<T> {
                val dateFormat = SimpleDateFormat(BaseConst.DATE_FORMAT)
                val dateTimeFormat = SimpleDateFormat(BaseConst.DATE_TIME_FORMAT)
                override fun fromString(value: String?): T? {
                    if (value.isNullOrBlank()) {
                        return null
                    }
                    var date: Date? = null
                    try {
                        date = dateTimeFormat.parse(value)
                    } catch(e: ParseException) {
                    }
                    if (date == null) {
                        try {
                            date = dateFormat.parse(value)
                        } catch(e: ParseException) {
                        }
                    }
                    return rawType.cast(date)
                }

                override fun toString(value: T?): String? {
                    if (value == null) {
                        return null
                    }
                    return dateTimeFormat.format(value)
                }
            }
        }
        return default
    }
}